Make data frame
Exclude Protocol 8 (mother)
Define Functions
## Func t test si boxplot simplu
func_t_box <- function(df, ind, pre_var, post_var, facet = FALSE, xlab = ""){
if(facet){
facet <- "Protocol"
}else{
facet <- NULL
}
df_modif <-
df %>%
select(ind, P, pre_var, post_var) %>%
tidyr::drop_na() %>%
gather(pre_var, post_var, key = "PrePost", value = "value") %>%
mutate_at(vars(c(1, 2)), funs(as.factor)) %>%
mutate(PrePost = factor(PrePost, levels = c(pre_var, post_var)))
if(!is.null(facet)){
df_modif <-
df_modif %>%
group_by(P) %>%
mutate(Protocol = paste0("Protocol = ", P, ", n = ", n()))
}
stat_comp <-
df_modif %>%
do(tidy(t.test(.$value ~ .$PrePost,
paired = TRUE,
data=.)))
plot <-
ggpubr::ggpaired(df_modif, x = "PrePost", y = "value", id = ind,
color = "PrePost", line.color = "gray", line.size = 0.4,
palette = c("#00AFBB", "#FC4E07"), legend = "none",
facet.by = facet, ncol = 3,
xlab = xlab) +
stat_summary(fun.data = mean_se, colour = "darkred") +
ggpubr::stat_compare_means(method = "t.test", paired = TRUE, label.x = as.numeric(df_modif$PrePost)-0.4, label.y = max(df_modif$value)+1) +
ggpubr::stat_compare_means(method = "t.test", paired = TRUE, label = "p.signif", comparisons = list(c(pre_var, post_var)))
print(stat_comp)
cat("\n")
print(plot)
cat("\n")
plot.new() # Need this workaround for interleaving tables and plots in R Markdown, within loop
dev.off()
}
heat_cor_plotly <- function(df, x_vars = NULL, y_vars = NULL, low_color = "cyan", high_color = "red", ...){
# inherit type = c("pearson","spearman") from Hmisc::rcorr()
library(ggplot2)
library(plotly)
library(reshape2)
library(Hmisc)
# use all numeric columns only, print message if non-numeric are found
numeric_cols <- unlist(lapply(df, is.numeric))
if(!all(numeric_cols)) message("Warning: Non-numeric columns were excluded!")
df <- df[, numeric_cols]
df_mat <- as.matrix(df)
rt <- Hmisc::rcorr(df_mat, ...)
# extract correlations, p-values and merge into another dataframe
mtlr <- reshape2::melt(rt$r, value.name = "Correlation")
mtlp <- reshape2::melt(rt$P, value.name = "P-Value")
mtl <- merge(mtlr, mtlp)
# give possibility to prune the correlation matrix
if(!is.null(x_vars)){
mtl <- mtl[(mtl$Var1 %in% x_vars), ]
}
if(!is.null(x_vars)){
mtl <- mtl[(mtl$Var2 %in% y_vars), ]
}
# want to avoid scientific notetion, but this doesnt work as numeric
# mtl$Correlation <- as.numeric(format(mtl$Correlation, digits = 4, scientific = FALSE)) # doesnt work
# mtl$`P-Value` <- as.numeric(format(mtl$`P-Value`, digits = 4, scientific = FALSE))
options(scipen = 999)
mtl$Correlation <- round(mtl$Correlation, 3)
mtl$`P-Value` <- round(mtl$`P-Value`, 3)
gx <-
ggplot2::ggplot(mtl,
aes(Var1, Var2,
fill = Correlation,
text = paste("P-val = ", `P-Value`))) +
ggplot2::geom_tile() +
ggplot2::scale_fill_gradient(low = low_color, high = high_color, limits = c(-1, 1), breaks = c(-1, -.5, 0, .5, 1)) +
ggplot2::theme_minimal() +
{if(any(nchar(names(df)) > 6)) ggplot2::theme(axis.text.x = element_text(angle = 90, hjust = 1))} # vertical x axis labels if lenghty
plotly::ggplotly(gx)
}
Plot
## Dodged Bar plot of Age and Gender
Data %>%
mutate(Varta_categ = cut(Varsta,
breaks=c(-Inf, 25, 30, 35, 40, 45, 50, 55, 60, Inf),
labels=c("<25","25-29","30-34", "35-39", "40-44", "45-49", "50-54", "55-59", "60>"),
right = FALSE)) %>%
mutate(Varsta = as.factor(Varsta),
Gen = as.factor(as.character(Gen))) %>%
mutate(Gen = forcats::fct_recode(Gen, "femin" = "1", "masculin" = "2")) %>%
dplyr::count(Varta_categ, Gen) %>% # Group by, then count number in each group
mutate(pct = prop.table(n)) %>% # Calculate percent within each var
ggplot(aes(x = Varta_categ, y = pct, fill = Gen, label = scales::percent(pct))) +
geom_col(position = 'dodge') +
geom_text(position = position_dodge(width = .9), # move to center of bars
vjust = -0.5, # nudge above top of bar
size = 3) +
scale_y_continuous(labels = scales::percent) +
ggtitle("") +
xlab("Varsta") + ylab("Percentage %") +
guides(fill = guide_legend(title = "Gen", ncol = 1)) +
scale_fill_grey(start = 0.8, end = 0.2, na.value = "red", aesthetics = "fill") +
theme(legend.position = "right", legend.direction = "vertical",
legend.justification = c(0, 1), panel.border = element_rect(fill = NA, colour = "black"))

## Pie chart
Data %>%
mutate(Gen = as.factor(as.character(Gen))) %>%
mutate(Gen = forcats::fct_recode(Gen, "femin" = "1", "masculin" = "2")) %>%
group_by(Gen) %>%
dplyr::summarise(counts = n()) %>%
mutate(prop = round(counts*100/sum(counts), 1),
lab.ypos = cumsum(prop) - .5*prop,
Percent = paste0(prop, " %")) %>%
ggpubr::ggpie(x = "prop", label = "Percent",
fill = "Gen", color = "white",
lab.pos = "in", lab.font = list(color = "white"),
palette = "grey")

Analyses
Simple before-after analyses with t test
VAS Stress
NANA

null device 1
VAS Stress
NANA

null device 1
Correlations: Anotimpuri - Calitate Amintiri (without P6, P7)
dateplot1 <- Data[, c("P", "Primavara", "Vara", "Toamna", "Iarna", "Media_s1", "Media_s2", "Media_s3", "SocDih_Part", "SocDih_FamN", "SocDih_FamInd", "SocDih_Priet", "SocDih_Amici", "SocDih_Necun", "SocDih_Antag", "SocDih_TotAprop", "SocDih_TotNeaprop", "STAI_T")]
names(dateplot1) <- c("P", "Primavara", "Vara", "Toamna", "Iarna", "S1- Valenta", "S2 - Vividness", "S3 - Relevanta", "Partener", "Familie nucleu", "Familie extinsa", "Prieteni", "Amici", "Necunoscuti", "Antagonisti", "Toti Apropiatii", "Toti Neapropiatii", "STAI_T")
dateplot1 <- subset(dateplot1, P!=6 & P!=7)
COR <- Hmisc::rcorr(as.matrix(dateplot1[,-1]))
M <- COR$r
P_MAT <- COR$P
corrplot::corrplot(M, method = "number", type = "upper", p.mat = P_MAT, sig.level = 0.05, insig = "blank", tl.col = "black", tl.cex = .9, tl.srt = 45)

Correlations: Personality - Qualities of Memories (without P6, P7)
dateplot2 <- Data[, c(24, 40, 56, 87:121, 126)]
names(dateplot2)[1:3] <- c("S1- Valenta", "S2 - Vividness", "S3 - Relevanta")
COR <- Hmisc::rcorr(as.matrix(dateplot2))
M <- COR$r
P_MAT <- COR$P
corrplot::corrplot(M, type = "upper", p.mat = P_MAT, sig.level = 0.05, insig = "blank", tl.col = "black", tl.cex = .7, cl.pos = "b", tl.srt = 45)

Correlations: Social - Personality
dateplot3 <- Data[, c(131:139, 87:121)]
names(dateplot3)[1:9] <- c("Partener", "Familie nucleu", "Familie extinsa", "Prieteni", "Amici", "Necunoscuti", "Antagonisti", "Toti Apropiatii", "Toti Neapropiatii")
COR <- Hmisc::rcorr(as.matrix(dateplot3))
M <- COR$r
P_MAT <- COR$P
corrplot::corrplot(M, type = "upper", p.mat = P_MAT, sig.level = 0.05, insig = "blank", tl.col = "black", tl.cex = .7, cl.pos = "b", tl.srt = 45)

Session Info
R version 3.6.1 (2019-07-05)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 8.1 x64 (build 9600)
Matrix products: default
locale:
[1] LC_COLLATE=Romanian_Romania.1250 LC_CTYPE=Romanian_Romania.1250 LC_MONETARY=Romanian_Romania.1250 LC_NUMERIC=C
[5] LC_TIME=Romanian_Romania.1250
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] Hmisc_4.1-1 Formula_1.2-3 survival_2.44-1.1 lattice_0.20-38 reshape2_1.4.3
[6] plotly_4.8.0 rio_0.5.16 scales_1.0.0 ggpubr_0.2 magrittr_1.5
[11] tadaatoolbox_0.16.1 summarytools_0.8.8 rstatix_0.2.0 broom_0.5.2 PerformanceAnalytics_1.5.2
[16] xts_0.11-2 zoo_1.8-4 psych_1.8.12 plyr_1.8.4 forcats_0.4.0
[21] stringr_1.4.0 dplyr_0.8.3 purrr_0.3.2 readr_1.3.1 tidyr_1.0.0
[26] tibble_2.1.3 ggplot2_3.2.1 tidyverse_1.2.1 papaja_0.1.0.9842 pacman_0.5.1
loaded via a namespace (and not attached):
[1] colorspace_1.4-1 ggsignif_0.4.0 pryr_0.1.4 ellipsis_0.2.0.1 htmlTable_1.12 base64enc_0.1-3 rstudioapi_0.8
[8] DT_0.5 manipulate_1.0.1 mvtnorm_1.0-11 lubridate_1.7.4 xml2_1.2.0 splines_3.6.1 codetools_0.2-16
[15] mnormt_1.5-5 knitr_1.24 zeallot_0.1.0 pixiedust_0.8.6 jsonlite_1.6 cluster_2.1.0 shiny_1.2.0
[22] compiler_3.6.1 httr_1.4.0 backports_1.1.4 assertthat_0.2.1 Matrix_1.2-17 lazyeval_0.2.2 cli_1.1.0
[29] later_0.7.5 acepack_1.4.1 htmltools_0.3.6 tools_3.6.1 gtable_0.3.0 glue_1.3.1 Rcpp_1.0.2
[36] carData_3.0-2 cellranger_1.1.0 vctrs_0.2.0 nlme_3.1-140 crosstalk_1.0.0 xfun_0.9 openxlsx_4.1.0
[43] rvest_0.3.2 mime_0.7 lifecycle_0.1.0 MASS_7.3-51.4 hms_0.5.1 promises_1.0.1 parallel_3.6.1
[50] expm_0.999-3 RColorBrewer_1.1-2 pwr_1.2-2 yaml_2.2.0 curl_3.2 gridExtra_2.3 pander_0.6.3
[57] rpart_4.1-15 latticeExtra_0.6-28 stringi_1.4.3 corrplot_0.84 nortest_1.0-4 checkmate_1.8.5 boot_1.3-22
[64] zip_1.0.0 rlang_0.4.0 pkgconfig_2.0.2 matrixStats_0.54.0 bitops_1.0-6 rapportools_1.0 htmlwidgets_1.3
[71] labeling_0.3 tidyselect_0.2.5 R6_2.4.0 DescTools_0.99.28 generics_0.0.2 pillar_1.4.2 haven_2.1.1
[78] foreign_0.8-71 withr_2.1.2 nnet_7.3-12 abind_1.4-5 RCurl_1.95-4.11 modelr_0.1.5 crayon_1.3.4
[85] car_3.0-2 viridis_0.5.1 grid_3.6.1 readxl_1.1.0 data.table_1.11.8 digest_0.6.20 xtable_1.8-4
[92] httpuv_1.4.5 munsell_0.5.0 viridisLite_0.3.0 quadprog_1.5-5
A work by Claudiu Papasteri
claudiu.papasteri@gmail.com
LS0tDQp0aXRsZTogIjxicj4gR2VuZXJhbCBQbG90cyBmb3IgTS4xLiAoQXV0b2Jpb2dyYXBoaWNhbCBNZW1vcmllcykiIA0Kc3VidGl0bGU6ICJJbml0aWFsIERhdGFzZXQiDQphdXRob3I6ICI8YnI+IENsYXVkaXUgUGFwYXN0ZXJpIg0KZGF0ZTogImByIGZvcm1hdChTeXMudGltZSgpLCAnJWQgJW0gJVknKWAiDQpvdXRwdXQ6IA0KICAgIGh0bWxfbm90ZWJvb2s6DQogICAgICAgICAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICAgICAgICAgIHRvYzogdHJ1ZQ0KICAgICAgICAgICAgdG9jX2RlcHRoOiAyDQogICAgICAgICAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUNCiAgICAgICAgICAgIHRoZW1lOiBzcGFjZWxhYg0KICAgICAgICAgICAgaGlnaGxpZ2h0OiB0YW5nbw0KICAgICAgICAgICAgZm9udC1mYW1pbHk6IEFyaWFsDQogICAgICAgICAgICBmaWdfd2lkdGg6IDEwDQogICAgICAgICAgICBmaWdfaGVpZ2h0OiA5DQogICAgIyB3b3JkX2RvY3VtZW50ICAgICAgICANCiAgICAjIHBkZl9kb2N1bWVudDogDQogICAgICAgICAgICAjIHRvYzogdHJ1ZQ0KICAgICAgICAgICAgIyB0b2NfZGVwdGg6IDINCiAgICAgICAgICAgICMgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgICAgICAgICAjIGZvbnRzaXplOiAxMXB0DQogICAgICAgICAgICAjIGdlb21ldHJ5OiBtYXJnaW49MWluDQogICAgICAgICAgICAjIGZpZ193aWR0aDogNw0KICAgICAgICAgICAgIyBmaWdfaGVpZ2h0OiA2DQogICAgICAgICAgICAjIGZpZ19jYXB0aW9uOiB0cnVlDQogICAgIyBnaXRodWJfZG9jdW1lbnQ6IA0KICAgICAgICAgICAgIyB0b2M6IHRydWUNCiAgICAgICAgICAgICMgdG9jX2RlcHRoOiAyDQogICAgICAgICAgICAjIGh0bWxfcHJldmlldzogZmFsc2UNCiAgICAgICAgICAgICMgZmlnX3dpZHRoOiA1DQogICAgICAgICAgICAjIGZpZ19oZWlnaHQ6IDUNCiAgICAgICAgICAgICMgZGV2OiBqcGVnDQotLS0NCg0KDQo8IS0tIFNldHVwIC0tPg0KDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0KIyBraW50ciBvcHRpb25zDQprbml0cjo6b3B0c19jaHVuayRzZXQoDQogIGNvbW1lbnQgPSAiIyIsDQogIGNvbGxhcHNlID0gVFJVRSwNCiAgZWNobyA9IFRSVUUsIA0KICB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwgZXJyb3IgPSBGQUxTRSwNCiAgY2FjaGUgPSBUUlVFICAgICAgICMgZWNobyA9IEZhbHNlIGZvciBnaXRodWJfZG9jdW1lbnQsIGJ1dCB3aWxsIGJlIGZvbGRlZCBpbiBodG1sX25vdGVib29rDQopDQoNCiMgR2VuZXJhbCBSIG9wdGlvbnMgYW5kIGluZm8NCnNldC5zZWVkKDExMSkgICAgICAgICAgICAgICAjIGluIGNhc2Ugd2UgdXNlIHJhbmRvbWl6ZWQgcHJvY2VkdXJlcyAgICAgICANCm9wdGlvbnMoc2NpcGVuID0gOTk5KSAgICAgICAjIHBvc2l0aXZlIHZhbHVlcyBiaWFzIHRvd2FyZHMgZml4ZWQgYW5kIG5lZ2F0aXZlIHRvd2FyZHMgc2NpZW50aWZpYyBub3RhdGlvbg0KDQojIExvYWQgcGFja2FnZXMNCmlmICghcmVxdWlyZSgicGFjbWFuIikpIGluc3RhbGwucGFja2FnZXMoInBhY21hbiIpDQpwYWNrYWdlcyA8LSBjKA0KICAicGFwYWphIiwNCiAgInRpZHl2ZXJzZSIsICJwbHlyIiwgICAgICANCiAgInBzeWNoIiwgIlBlcmZvcm1hbmNlQW5hbHl0aWNzIiwgICAgICAgICAgDQogICJicm9vbSIsICJyc3RhdGl4IiwNCiAgInN1bW1hcnl0b29scyIsICJ0YWRhYXRvb2xib3giLCAgICAgICAgICAgDQogICJnZ3Bsb3QyIiwgImdncHViciIsICJzY2FsZXMiLCAgICAgICAgDQogICJyaW8iDQogICMgLCAuLi4NCikNCmlmICghcmVxdWlyZSgicGFjbWFuIikpIGluc3RhbGwucGFja2FnZXMoInBhY21hbiIpDQpwYWNtYW46OnBfbG9hZChjaGFyID0gcGFja2FnZXMpDQoNCiMgVGhlbWVzIGZvciBnZ3Bsb3QyIHBsb3RpbmcgKGhlcmUgdXNlZCBBUEEgc3R5bGUpDQp0aGVtZV9zZXQodGhlbWVfYXBhKCkpDQoNCiMgVGFibGVzIGtuaXR0aW5nIHRvIFdvcmQNCmRvYy50eXBlIDwtIGtuaXRyOjpvcHRzX2tuaXQkZ2V0KCdybWFya2Rvd24ucGFuZG9jLnRvJykgICMgdGhlbiBmb3JtYXQgdGFibGVzIHVzaW5nIGFuIGlmIHN0YXRlbWVudCBsaWtlOg0KIyBpZiAoZG9jLnR5cGUgPT0gImRvY3giKSB7IHBhbmRlcjo6cGFuZGVyKGRmKSB9IGVsc2UgeyBrbml0cjo6a2FibGUoZGYpIH0NCg0KIyBTZXQgd2QgZm9yIE5vdGVib29rDQpmb2xkZXIgPC0gIkM6L1VzZXJzL01paGFpL0Rlc2t0b3AvUiBOb3RlYm9va3Mvbm90ZWJvb2tzL00uMS4gR2VuZXJhbCINCiMga25pdHI6Om9wdHNfa25pdCRzZXQocm9vdC5kaXIgPSBub3JtYWxpemVQYXRoKGZvbGRlcikpDQpgYGANCg0KDQoNCg0KDQo8IS0tIFJlcG9ydCAtLT4NCg0KDQojIFJlYWQNCg0KYGBge3IgcmVkX2NsZWFuX3JlY29kZV9tZXJnZSwgcmVzdWx0cz0naGlkZSd9DQojfn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fg0KIyBSZWFkDQojfn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fg0KDQojIyBSZWFkIGZpbGVzDQpmaWxlIDwtICJEYXRlIENvbXBsZXRlIE0xIHYuMTMgc2lQUEdHU1JhbWlsYXphLnNhdiINCg0KIyBzZXR3ZChmb2xkZXIpDQpEYXRhIDwtIHJpbzo6aW1wb3J0KGZpbGUucGF0aChmb2xkZXIsIGZpbGUpKQ0KYGBgDQoNCg0KIyBNYWtlIGRhdGEgZnJhbWUNCg0KYGBge3IgZGZfZXhjZWx9DQpEYXRhICU+JQ0KICBkcGx5cjo6c2VsZWN0KC1OdW1lKSAlPiUNCiAgICBEVDo6ZGF0YXRhYmxlKA0KICAgICAgZXh0ZW5zaW9ucyA9ICdCdXR0b25zJywNCiAgICAgIG9wdGlvbnMgPSBsaXN0KHBhZ2VMZW5ndGggPSAxMCwNCiAgICAgICAgICAgICAgICAgICAgIHNjcm9sbFg9JzUwMHB4JywNCiAgICAgICAgICAgICAgICAgICAgIGRvbSA9ICdCZnJ0aXAnLA0KICAgICAgICAgICAgICAgICAgICAgYnV0dG9ucyA9IGMoJ2V4Y2VsJywgImNzdiIpKSkNCmBgYA0KDQoNCiMjIEV4Y2x1ZGUgUHJvdG9jb2wgOCAobW90aGVyKQ0KDQpgYGB7ciBkZl9maWx0ZXJlZH0NCkRhdGEgPC0gDQogIERhdGEgJT4lDQogIGZpbHRlcihQICE9IDgpDQpgYGANCg0KDQojIERlZmluZSBGdW5jdGlvbnMgDQoNCmBgYHtyIGRlZl9mdW5jX3R0ZXN0LCBoaWRlPVRSVUUsIHJlc3VsdHM9J2FzaXMnfQ0KIyMgRnVuYyB0IHRlc3Qgc2kgYm94cGxvdCBzaW1wbHUNCmZ1bmNfdF9ib3ggPC0gZnVuY3Rpb24oZGYsIGluZCwgcHJlX3ZhciwgcG9zdF92YXIsIGZhY2V0ID0gRkFMU0UsIHhsYWIgPSAiIil7ICANCiAgaWYoZmFjZXQpew0KICAgIGZhY2V0IDwtICJQcm90b2NvbCINCiAgfWVsc2V7DQogICAgZmFjZXQgPC0gTlVMTA0KICB9DQogIA0KICBkZl9tb2RpZiA8LQ0KICAgIGRmICU+JQ0KICAgIHNlbGVjdChpbmQsIFAsIHByZV92YXIsIHBvc3RfdmFyKSAlPiUgDQogICAgdGlkeXI6OmRyb3BfbmEoKSAlPiUNCiAgICBnYXRoZXIocHJlX3ZhciwgcG9zdF92YXIsIGtleSA9ICJQcmVQb3N0IiwgdmFsdWUgPSAidmFsdWUiKSAlPiUgDQogICAgbXV0YXRlX2F0KHZhcnMoYygxLCAyKSksIGZ1bnMoYXMuZmFjdG9yKSkgJT4lIA0KICAgIG11dGF0ZShQcmVQb3N0ID0gZmFjdG9yKFByZVBvc3QsIGxldmVscyA9IGMocHJlX3ZhciwgcG9zdF92YXIpKSkgDQogIA0KICBpZighaXMubnVsbChmYWNldCkpew0KICAgIGRmX21vZGlmIDwtDQogICAgICBkZl9tb2RpZiAlPiUNCiAgICAgIGdyb3VwX2J5KFApICU+JQ0KICAgICAgbXV0YXRlKFByb3RvY29sID0gcGFzdGUwKCJQcm90b2NvbCA9ICIsIFAsICIsIG4gPSAiLCBuKCkpKQ0KICB9DQogIA0KICBzdGF0X2NvbXAgPC0NCiAgICBkZl9tb2RpZiAlPiUgDQogICAgZG8odGlkeSh0LnRlc3QoLiR2YWx1ZSB+IC4kUHJlUG9zdCwNCiAgICAgICAgICAgICAgICAgICBwYWlyZWQgPSBUUlVFLA0KICAgICAgICAgICAgICAgICAgIGRhdGE9LikpKQ0KICANCiAgcGxvdCA8LSANCiAgICBnZ3B1YnI6OmdncGFpcmVkKGRmX21vZGlmLCB4ID0gIlByZVBvc3QiLCB5ID0gInZhbHVlIiwgaWQgPSBpbmQsIA0KICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiUHJlUG9zdCIsIGxpbmUuY29sb3IgPSAiZ3JheSIsIGxpbmUuc2l6ZSA9IDAuNCwNCiAgICAgICAgICAgICAgICAgICAgIHBhbGV0dGUgPSBjKCIjMDBBRkJCIiwgIiNGQzRFMDciKSwgbGVnZW5kID0gIm5vbmUiLA0KICAgICAgICAgICAgICAgICAgICAgZmFjZXQuYnkgPSBmYWNldCwgbmNvbCA9IDMsIA0KICAgICAgICAgICAgICAgICAgICAgeGxhYiA9IHhsYWIpICsNCiAgICBzdGF0X3N1bW1hcnkoZnVuLmRhdGEgPSBtZWFuX3NlLCAgY29sb3VyID0gImRhcmtyZWQiKSArDQogICAgZ2dwdWJyOjpzdGF0X2NvbXBhcmVfbWVhbnMobWV0aG9kID0gInQudGVzdCIsIHBhaXJlZCA9IFRSVUUsIGxhYmVsLnggPSBhcy5udW1lcmljKGRmX21vZGlmJFByZVBvc3QpLTAuNCwgbGFiZWwueSA9IG1heChkZl9tb2RpZiR2YWx1ZSkrMSkgKyANCiAgICBnZ3B1YnI6OnN0YXRfY29tcGFyZV9tZWFucyhtZXRob2QgPSAidC50ZXN0IiwgcGFpcmVkID0gVFJVRSwgbGFiZWwgPSAicC5zaWduaWYiLCBjb21wYXJpc29ucyA9IGxpc3QoYyhwcmVfdmFyLCBwb3N0X3ZhcikpKQ0KICANCiAgcHJpbnQoc3RhdF9jb21wKQ0KICBjYXQoIlxuIikgICAgICAgICAgICAgICAgICAgICAgDQogIHByaW50KHBsb3QpDQogIGNhdCgiXG4iKQ0KICBwbG90Lm5ldygpICAgICAgICAgICAgICAgICAgICAgIyBOZWVkIHRoaXMgd29ya2Fyb3VuZCBmb3IgaW50ZXJsZWF2aW5nIHRhYmxlcyBhbmQgcGxvdHMgaW4gUiBNYXJrZG93biwgd2l0aGluIGxvb3ANCiAgZGV2Lm9mZigpDQp9DQpgYGANCg0KDQpgYGB7ciBkZWZfZnVuY19oZWF0Y29ycGxvdGx5LCBoaWRlPVRSVUUsIHJlc3VsdHM9J2FzaXMnfQ0KaGVhdF9jb3JfcGxvdGx5IDwtIGZ1bmN0aW9uKGRmLCB4X3ZhcnMgPSBOVUxMLCB5X3ZhcnMgPSBOVUxMLCBsb3dfY29sb3IgPSAiY3lhbiIsICBoaWdoX2NvbG9yID0gInJlZCIsICAuLi4peyAgIA0KICAjIGluaGVyaXQgdHlwZSA9IGMoInBlYXJzb24iLCJzcGVhcm1hbiIpIGZyb20gSG1pc2M6OnJjb3JyKCkgDQogIGxpYnJhcnkoZ2dwbG90MikNCiAgbGlicmFyeShwbG90bHkpDQogIGxpYnJhcnkocmVzaGFwZTIpDQogIGxpYnJhcnkoSG1pc2MpDQogIA0KICAjIHVzZSBhbGwgbnVtZXJpYyBjb2x1bW5zIG9ubHksIHByaW50IG1lc3NhZ2UgaWYgbm9uLW51bWVyaWMgYXJlIGZvdW5kDQogIG51bWVyaWNfY29scyA8LSB1bmxpc3QobGFwcGx5KGRmLCBpcy5udW1lcmljKSkNCiAgaWYoIWFsbChudW1lcmljX2NvbHMpKSBtZXNzYWdlKCJXYXJuaW5nOiBOb24tbnVtZXJpYyBjb2x1bW5zIHdlcmUgZXhjbHVkZWQhIikNCiAgZGYgPC0gZGZbLCBudW1lcmljX2NvbHNdDQogIA0KICBkZl9tYXQgPC0gYXMubWF0cml4KGRmKQ0KICBydCA8LSBIbWlzYzo6cmNvcnIoZGZfbWF0LCAuLi4pDQogIA0KICAjIGV4dHJhY3QgY29ycmVsYXRpb25zLCBwLXZhbHVlcyBhbmQgbWVyZ2UgaW50byBhbm90aGVyIGRhdGFmcmFtZQ0KICBtdGxyIDwtIHJlc2hhcGUyOjptZWx0KHJ0JHIsIHZhbHVlLm5hbWUgPSAiQ29ycmVsYXRpb24iKQ0KICBtdGxwIDwtIHJlc2hhcGUyOjptZWx0KHJ0JFAsIHZhbHVlLm5hbWUgPSAiUC1WYWx1ZSIpDQogIA0KICBtdGwgPC0gbWVyZ2UobXRsciwgbXRscCkNCiAgDQogICMgZ2l2ZSBwb3NzaWJpbGl0eSB0byBwcnVuZSB0aGUgY29ycmVsYXRpb24gbWF0cml4DQogIGlmKCFpcy5udWxsKHhfdmFycykpew0KICAgIG10bCA8LSBtdGxbKG10bCRWYXIxICVpbiUgeF92YXJzKSwgXQ0KICB9DQogIGlmKCFpcy5udWxsKHhfdmFycykpew0KICAgIG10bCA8LSBtdGxbKG10bCRWYXIyICVpbiUgeV92YXJzKSwgXQ0KICB9DQogIA0KICAjIHdhbnQgdG8gYXZvaWQgc2NpZW50aWZpYyBub3RldGlvbiwgYnV0IHRoaXMgZG9lc250IHdvcmsgYXMgbnVtZXJpYw0KICAjIG10bCRDb3JyZWxhdGlvbiA8LSBhcy5udW1lcmljKGZvcm1hdChtdGwkQ29ycmVsYXRpb24sIGRpZ2l0cyA9IDQsIHNjaWVudGlmaWMgPSBGQUxTRSkpICAjIGRvZXNudCB3b3JrDQogICMgbXRsJGBQLVZhbHVlYCA8LSBhcy5udW1lcmljKGZvcm1hdChtdGwkYFAtVmFsdWVgLCBkaWdpdHMgPSA0LCBzY2llbnRpZmljID0gRkFMU0UpKSANCiAgb3B0aW9ucyhzY2lwZW4gPSA5OTkpDQogIG10bCRDb3JyZWxhdGlvbiA8LSByb3VuZChtdGwkQ29ycmVsYXRpb24sIDMpDQogIG10bCRgUC1WYWx1ZWAgPC0gcm91bmQobXRsJGBQLVZhbHVlYCwgMykNCg0KICBneCA8LQ0KICAgIGdncGxvdDI6OmdncGxvdChtdGwsIA0KICAgICAgICAgICBhZXMoVmFyMSwgVmFyMiwgDQogICAgICAgICAgICAgICBmaWxsID0gQ29ycmVsYXRpb24sICANCiAgICAgICAgICAgICAgIHRleHQgPSBwYXN0ZSgiUC12YWwgPSAiLCBgUC1WYWx1ZWApKSkgKw0KICAgIGdncGxvdDI6Omdlb21fdGlsZSgpICsgDQogICAgZ2dwbG90Mjo6c2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSBsb3dfY29sb3IsICBoaWdoID0gaGlnaF9jb2xvciwgbGltaXRzID0gYygtMSwgMSksIGJyZWFrcyA9IGMoLTEsIC0uNSwgMCwgLjUsIDEpKSArDQogICAgZ2dwbG90Mjo6dGhlbWVfbWluaW1hbCgpICsNCiAgICB7aWYoYW55KG5jaGFyKG5hbWVzKGRmKSkgPiA2KSkgZ2dwbG90Mjo6dGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAxKSl9ICAjIHZlcnRpY2FsIHggYXhpcyBsYWJlbHMgaWYgbGVuZ2h0eQ0KICBwbG90bHk6OmdncGxvdGx5KGd4KSAgDQp9DQpgYGANCg0KDQojIFBsb3QNCg0KYGBge3IgcGxvdDEsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTYsIHJlc3VsdHM9J2FzaXMnfQ0KIyMgRG9kZ2VkIEJhciBwbG90IG9mIEFnZSBhbmQgR2VuZGVyDQpEYXRhICAlPiUNCiAgbXV0YXRlKFZhcnRhX2NhdGVnID0gY3V0KFZhcnN0YSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3M9YygtSW5mLCAyNSwgMzAsIDM1LCA0MCwgNDUsIDUwLCA1NSwgNjAsIEluZiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIjwyNSIsIjI1LTI5IiwiMzAtMzQiLCAiMzUtMzkiLCAiNDAtNDQiLCAiNDUtNDkiLCAiNTAtNTQiLCAiNTUtNTkiLCAiNjA+IiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgcmlnaHQgPSBGQUxTRSkpICU+JSAgDQogIG11dGF0ZShWYXJzdGEgPSBhcy5mYWN0b3IoVmFyc3RhKSwNCiAgICAgICAgIEdlbiA9IGFzLmZhY3Rvcihhcy5jaGFyYWN0ZXIoR2VuKSkpICU+JQ0KICBtdXRhdGUoR2VuID0gZm9yY2F0czo6ZmN0X3JlY29kZShHZW4sICJmZW1pbiIgPSAiMSIsICJtYXNjdWxpbiIgPSAiMiIpKSAlPiUNCiAgZHBseXI6OmNvdW50KFZhcnRhX2NhdGVnLCBHZW4pICU+JSAgICAgICAgICAgICAgICAgICAgICAgICMgR3JvdXAgYnksIHRoZW4gY291bnQgbnVtYmVyIGluIGVhY2ggZ3JvdXANCiAgbXV0YXRlKHBjdCA9IHByb3AudGFibGUobikpICU+JSAgICAgICAgICAgICAgICAgICAgICMgQ2FsY3VsYXRlIHBlcmNlbnQgd2l0aGluIGVhY2ggdmFyDQogIGdncGxvdChhZXMoeCA9IFZhcnRhX2NhdGVnLCB5ID0gcGN0LCBmaWxsID0gR2VuLCBsYWJlbCA9IHNjYWxlczo6cGVyY2VudChwY3QpKSkgKyANCiAgICBnZW9tX2NvbChwb3NpdGlvbiA9ICdkb2RnZScpICsgDQogICAgZ2VvbV90ZXh0KHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAuOSksICAgICMgbW92ZSB0byBjZW50ZXIgb2YgYmFycw0KICAgICAgICAgICAgICB2anVzdCA9IC0wLjUsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIG51ZGdlIGFib3ZlIHRvcCBvZiBiYXINCiAgICAgICAgICAgICAgc2l6ZSA9IDMpICsgDQogICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudCkgKw0KICAgIGdndGl0bGUoIiIpICsNCiAgICB4bGFiKCJWYXJzdGEiKSArIHlsYWIoIlBlcmNlbnRhZ2UgJSIpICsgDQogICAgZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQodGl0bGUgPSAiR2VuIiwgbmNvbCA9IDEpKSArIA0KICAgIHNjYWxlX2ZpbGxfZ3JleShzdGFydCA9IDAuOCwgZW5kID0gMC4yLCBuYS52YWx1ZSA9ICJyZWQiLCBhZXN0aGV0aWNzID0gImZpbGwiKSArDQogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IiwgbGVnZW5kLmRpcmVjdGlvbiA9ICJ2ZXJ0aWNhbCIsIA0KICAgICAgICAgIGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gYygwLCAxKSwgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGZpbGwgPSBOQSwgY29sb3VyID0gImJsYWNrIikpDQpgYGANCg0KDQpgYGB7ciBwbG90MiwgZmlnLndpZHRoPTYsIGZpZy5oZWlnaHQ9NiwgcmVzdWx0cz0nYXNpcyd9DQojIyBQaWUgY2hhcnQNCkRhdGEgICU+JQ0KICBtdXRhdGUoR2VuID0gYXMuZmFjdG9yKGFzLmNoYXJhY3RlcihHZW4pKSkgJT4lDQogIG11dGF0ZShHZW4gPSBmb3JjYXRzOjpmY3RfcmVjb2RlKEdlbiwgImZlbWluIiA9ICIxIiwgIm1hc2N1bGluIiA9ICIyIikpICU+JQ0KICBncm91cF9ieShHZW4pICU+JQ0KICBkcGx5cjo6c3VtbWFyaXNlKGNvdW50cyA9IG4oKSkgJT4lDQogIG11dGF0ZShwcm9wID0gcm91bmQoY291bnRzKjEwMC9zdW0oY291bnRzKSwgMSksDQogICAgICAgICBsYWIueXBvcyA9IGN1bXN1bShwcm9wKSAtIC41KnByb3AsDQogICAgICAgICBQZXJjZW50ID0gcGFzdGUwKHByb3AsICIgJSIpKSAlPiUgDQogIGdncHVicjo6Z2dwaWUoeCA9ICJwcm9wIiwgbGFiZWwgPSAiUGVyY2VudCIsDQogICAgICAgICAgICAgICAgZmlsbCA9ICJHZW4iLCBjb2xvciA9ICJ3aGl0ZSIsIA0KICAgICAgICAgICAgICAgIGxhYi5wb3MgPSAiaW4iLCBsYWIuZm9udCA9IGxpc3QoY29sb3IgPSAid2hpdGUiKSwNCiAgICAgICAgICAgICAgICBwYWxldHRlID0gImdyZXkiKQ0KYGBgDQoNCg0KDQojIEFuYWx5c2VzDQoNCiMjIFNpbXBsZSBiZWZvcmUtYWZ0ZXIgYW5hbHlzZXMgd2l0aCB0IHRlc3QNCg0KYGBge3IgdF90ZXN0MSwgZmlnLndpZHRoPTUsIGZpZy5oZWlnaHQ9NiwgcmVzdWx0cz0nYXNpcyd9DQojIyBTaW1wbGUgYmVmb3JlLWFmdGVyIGFuYWx5c2VzIHdpdGggdCB0ZXN0DQpjYXQoIiMjIyMgVkFTIFN0cmVzcyIpDQpmdW5jX3RfYm94KERhdGEsIGluZCA9ICJJRCIsICJTdHJlc19wcmUiLCAiU3RyZXNfcG9zdCIsIGZhY2V0ID0gRkFMU0UpIA0KYGBgDQoNCg0KYGBge3IgdF90ZXN0MiwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9MTIsIHJlc3VsdHM9J2FzaXMnfQ0KIyMgU2ltcGxlIGJlZm9yZS1hZnRlciBhbmFseXNlcyB3aXRoIHQgdGVzdA0KY2F0KCIjIyMjIFZBUyBTdHJlc3MiKQ0KZnVuY190X2JveChEYXRhLCBpbmQgPSAiSUQiLCAiU3RyZXNfcHJlIiwgIlN0cmVzX3Bvc3QiLCBmYWNldCA9IFRSVUUpIA0KYGBgDQoNCg0KIyMgQ29ycmVsYXRpb25zOiBBbm90aW1wdXJpIC0gQ2FsaXRhdGUgQW1pbnRpcmkgKHdpdGhvdXQgUDYsIFA3KQ0KDQpgYGB7ciBjb3IxLCBmaWcud2lkdGg9OSwgZmlnLmhlaWdodD05LCByZXN1bHRzPSdhc2lzJ30NCmRhdGVwbG90MSA8LSBEYXRhWywgYygiUCIsICJQcmltYXZhcmEiLCAiVmFyYSIsICJUb2FtbmEiLCAiSWFybmEiLCAiTWVkaWFfczEiLCAiTWVkaWFfczIiLCAiTWVkaWFfczMiLCAgIlNvY0RpaF9QYXJ0IiwgICJTb2NEaWhfRmFtTiIsICAiU29jRGloX0ZhbUluZCIsICAiU29jRGloX1ByaWV0IiwgICJTb2NEaWhfQW1pY2kiLCAgIlNvY0RpaF9OZWN1biIsICAiU29jRGloX0FudGFnIiwgICJTb2NEaWhfVG90QXByb3AiLCAgIlNvY0RpaF9Ub3ROZWFwcm9wIiwgIlNUQUlfVCIpXSANCm5hbWVzKGRhdGVwbG90MSkgPC0gYygiUCIsICJQcmltYXZhcmEiLCAiVmFyYSIsICJUb2FtbmEiLCAiSWFybmEiLCAiUzEtIFZhbGVudGEiLCAiUzIgLSBWaXZpZG5lc3MiLCAiUzMgLSBSZWxldmFudGEiLCAgIlBhcnRlbmVyIiwgICJGYW1pbGllIG51Y2xldSIsICAiRmFtaWxpZSBleHRpbnNhIiwgICJQcmlldGVuaSIsICAiQW1pY2kiLCAgIk5lY3Vub3NjdXRpIiwgICJBbnRhZ29uaXN0aSIsICAiVG90aSBBcHJvcGlhdGlpIiwgICJUb3RpIE5lYXByb3BpYXRpaSIsICJTVEFJX1QiKQ0KZGF0ZXBsb3QxIDwtIHN1YnNldChkYXRlcGxvdDEsIFAhPTYgJiBQIT03KQ0KDQpDT1IgPC0gSG1pc2M6OnJjb3JyKGFzLm1hdHJpeChkYXRlcGxvdDFbLC0xXSkpICAgDQpNIDwtIENPUiRyDQpQX01BVCA8LSBDT1IkUA0KY29ycnBsb3Q6OmNvcnJwbG90KE0sIG1ldGhvZCA9ICJudW1iZXIiLCB0eXBlID0gInVwcGVyIiwgcC5tYXQgPSBQX01BVCwgc2lnLmxldmVsID0gMC4wNSwgaW5zaWcgPSAiYmxhbmsiLCB0bC5jb2wgPSAiYmxhY2siLCB0bC5jZXggPSAuOSwgdGwuc3J0ID0gNDUpICANCmBgYA0KDQoNCmBgYHtyIGhlYXRfY29yMSwgZmlnLndpZHRoPTksIGZpZy5oZWlnaHQ9OSwgcmVzdWx0cz0nYXNpcyd9DQpoZWF0X2Nvcl9wbG90bHkoZGF0ZXBsb3QxWywtMV0pDQpgYGANCg0KDQojIyBDb3JyZWxhdGlvbnM6IFBlcnNvbmFsaXR5IC0gUXVhbGl0aWVzIG9mIE1lbW9yaWVzICh3aXRob3V0IFA2LCBQNykNCg0KYGBge3IgY29yMiwgZmlnLndpZHRoPTExLCBmaWcuaGVpZ2h0PTExLCByZXN1bHRzPSdhc2lzJ30NCmRhdGVwbG90MiA8LSBEYXRhWywgYygyNCwgNDAsIDU2LCA4NzoxMjEsIDEyNildIA0KbmFtZXMoZGF0ZXBsb3QyKVsxOjNdIDwtIGMoIlMxLSBWYWxlbnRhIiwgIlMyIC0gVml2aWRuZXNzIiwgIlMzIC0gUmVsZXZhbnRhIikNCg0KQ09SIDwtIEhtaXNjOjpyY29ycihhcy5tYXRyaXgoZGF0ZXBsb3QyKSkgICANCk0gPC0gQ09SJHINClBfTUFUIDwtIENPUiRQDQpjb3JycGxvdDo6Y29ycnBsb3QoTSwgdHlwZSA9ICJ1cHBlciIsIHAubWF0ID0gUF9NQVQsIHNpZy5sZXZlbCA9IDAuMDUsIGluc2lnID0gImJsYW5rIiwgdGwuY29sID0gImJsYWNrIiwgdGwuY2V4ID0gLjcsIGNsLnBvcyA9ICJiIiwgdGwuc3J0ID0gNDUpDQpgYGANCg0KDQpgYGB7ciBoZWF0X2NvcjIsIGZpZy53aWR0aD00LCBmaWcuaGVpZ2h0PTEyLCByZXN1bHRzPSdhc2lzJ30NCmhlYXRfY29yX3Bsb3RseShkYXRlcGxvdDIsIHhfdmFycyA9IG5hbWVzKGRhdGVwbG90MilbMTozXSwgeV92YXJzID0gbmFtZXMoZGF0ZXBsb3QyKVstKDE6MyldKQ0KYGBgDQoNCg0KIyMgQ29ycmVsYXRpb25zOiBTb2NpYWwgLSBQZXJzb25hbGl0eQ0KDQpgYGB7ciBjb3IzLCBmaWcud2lkdGg9MTEsIGZpZy5oZWlnaHQ9MTEsIHJlc3VsdHM9J2FzaXMnfQ0KZGF0ZXBsb3QzIDwtIERhdGFbLCBjKDEzMToxMzksIDg3OjEyMSldDQpuYW1lcyhkYXRlcGxvdDMpWzE6OV0gPC0gYygiUGFydGVuZXIiLCAgIkZhbWlsaWUgbnVjbGV1IiwgICJGYW1pbGllIGV4dGluc2EiLCAgIlByaWV0ZW5pIiwgICJBbWljaSIsICAiTmVjdW5vc2N1dGkiLCAgIkFudGFnb25pc3RpIiwgICJUb3RpIEFwcm9waWF0aWkiLCAgIlRvdGkgTmVhcHJvcGlhdGlpIikNCg0KQ09SIDwtIEhtaXNjOjpyY29ycihhcy5tYXRyaXgoZGF0ZXBsb3QzKSkgICANCk0gPC0gQ09SJHINClBfTUFUIDwtIENPUiRQDQpjb3JycGxvdDo6Y29ycnBsb3QoTSwgdHlwZSA9ICJ1cHBlciIsIHAubWF0ID0gUF9NQVQsIHNpZy5sZXZlbCA9IDAuMDUsIGluc2lnID0gImJsYW5rIiwgdGwuY29sID0gImJsYWNrIiwgdGwuY2V4ID0gLjcsIGNsLnBvcyA9ICJiIiwgdGwuc3J0ID0gNDUpDQpgYGANCg0KDQpgYGB7ciBoZWF0X2NvcjMsIGZpZy53aWR0aD02LCBmaWcuaGVpZ2h0PTEyLCByZXN1bHRzPSdhc2lzJ30NCmhlYXRfY29yX3Bsb3RseShkYXRlcGxvdDMsIHhfdmFycyA9IG5hbWVzKGRhdGVwbG90MylbMTo5XSwgeV92YXJzID0gbmFtZXMoZGF0ZXBsb3QzKVstKDE6OSldKQ0KYGBgDQoNCg0KDQoNCg0KDQo8YnI+DQoNCg0KDQoNCg0KPCEtLSBTZXNzaW9uIEluZm8gYW5kIExpY2Vuc2UgLS0+DQoNCjxicj4NCg0KIyBTZXNzaW9uIEluZm8NCmBgYHtyIHNlc3Npb25faW5mbywgZWNobyA9IEZBTFNFLCByZXN1bHRzID0gJ21hcmt1cCd9DQpzZXNzaW9uSW5mbygpICAgIA0KYGBgDQoNCjwhLS0gRm9vdGVyIC0tPg0KJm5ic3A7DQo8aHIgLz4NCjxwIHN0eWxlPSJ0ZXh0LWFsaWduOiBjZW50ZXI7Ij5BIHdvcmsgYnkgPGEgaHJlZj0iaHR0cHM6Ly9naXRodWIuY29tL0NsYXVkaXVQYXBhc3RlcmkvIj5DbGF1ZGl1IFBhcGFzdGVyaTwvYT48L3A+DQo8cCBzdHlsZT0idGV4dC1hbGlnbjogY2VudGVyOyI+PHNwYW4gc3R5bGU9ImNvbG9yOiAjODA4MDgwOyI+PGVtPmNsYXVkaXUucGFwYXN0ZXJpQGdtYWlsLmNvbTwvZW0+PC9zcGFuPjwvcD4NCiZuYnNwOw0K